#include "DoubleLinkedList.h"

DList* init_list() {
    DList* list = (DList*)malloc(sizeof(DList));
    list->head = NULL;
    list->tail = NULL;
    return list;
}

Node* create_node(ElemType data) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    new_node->data = data;
    new_node->prev = NULL;
    new_node->next = NULL;
    return new_node;
}

Node* create_node_with_pointer(ElemType data, Node* prev, Node* next) {
    Node* new_node = (Node*)malloc(sizeof(Node));
    new_node->data = data;
    new_node->prev = prev;
    new_node->next = next;
    return new_node;
}

void add_head(DList* list, ElemType data) {
    Node* new_node = create_node_with_pointer(data, NULL, list->head);
    if (list->head == NULL) {
        list->tail = new_node;
    } else {
        list->head->prev = new_node;
    }
    list->head = new_node;
}

void add_tail(DList* list, ElemType data) {
    Node* new_node = create_node_with_pointer(data, list->tail, NULL);
    if (list->tail == NULL) {
        list->head = new_node;
    } else {
        list->tail->next = new_node;
    }
    list->tail = new_node;
}

void add_node(DList* list, ElemType data, int index) {
    if (index < 0) {
        printf("add_node: illegal index\n");
        return;
    }

    // 处理空链表的情况
    if (list->head == NULL) {
        if (index == 0) {
            add_head(list, data);
        } else {
            printf("add_node: illegal index\n");
        }
        return;
    }

    // 处理在头部插入的情况
    if (index == 0) {
        add_head(list, data);
        return;
    }

    // 查找插入位置的前一个节点
    Node* cur = list->head;
    for (int i = 0; i < index - 1; ++i) {
        cur = cur->next;
        if (cur == NULL) {
            printf("add_node: illegal index\n");
            return;
        }
    }

    // 处理在尾部插入的情况
    if (cur->next == NULL) {
        add_tail(list, data);
        return;
    }

    // 在中间插入新节点
    Node* new_node = create_node_with_pointer(data, cur, cur->next);
    cur->next->prev = new_node;
    cur->next = new_node;
}

void del_head(DList* list) {
    Node* del = list->head;
    if (del == NULL) {
        printf("del_head: empty list\n");
        return;
    }
    list->head = del->next;
    if (list->head == NULL) {
        list->tail = NULL;
    } else {
        list->head->prev = NULL;
    }
    free(del);
}

void del_tail(DList* list) {
    Node* del = list->tail;
    if (del == NULL) {
        printf("del_tail: empty list\n");
        return;
    }
    list->tail = del->prev;
    if (list->tail == NULL) {
        list->head = NULL;
    } else {
        list->tail->next = NULL;
    }
    free(del);
}

void del_node(DList* list, int index) {
    if (index < 0) {
        printf("del_node: illegal index\n");
        return;
    }

    // 处理空链表的情况
    if (list->head == NULL) {
        printf("del_node: empty list\n");
        return;
    }

    // 处理删除头部节点的情况
    if (index == 0) {
        del_head(list);
    }
    // 查找要删除的节点
    Node* cur = list->head;
    for (int i = 0; i < index; ++i) {
        cur = cur->next;
        if (cur == NULL) {
            printf("del_node: illegal index\n");
            return;
        }
    }

    // 处理删除尾部节点的情况
    if (cur->next == NULL) {
        del_tail(list);
    } else {
        // 在中间删除节点
        cur->prev->next = cur->next;
        cur->next->prev = cur->prev;
        free(cur);
    }
}

ElemType get_head(DList* list) {
    if (list->head == NULL) {
        printf("get_head: empty list\n");
        return -1;
    }
    return list->head->data;
}

ElemType get_tail(DList* list) {
    if (list->tail == NULL) {
        printf("get_tail: empty list\n");
        return -1;
    }
    return list->tail->data;
}

ElemType get_node(DList* list, int index) {
    if (index < 0) {
        printf("get_node: illegal index\n");
        return -1;
    }

    if (list->head == NULL) {
        printf("get_node: empty list\n");
        return -1;
    }

    Node* cur = list->head;
    for (int i = 0; i < index; ++i) {
        cur = cur->next;
    }
    return cur->data;
}

int get_length(DList* list) {
    int len = 0;
    for (Node* cur = list->head; cur != NULL; cur = cur->next) {
        len++;
    }
    return len;
}

void print_DList_from_head(DList* list) {
    Node* cur = list->head;
    printf("[HEAD -- ");
    while (cur != NULL) {
        printf("%d -- ", cur->data);
        cur = cur->next;
    }
    printf("TAIL]\n");
}

void print_DList_from_tail(DList* list) {
    Node* cur = list->tail;
    printf("[TAIL -- ");
    while (cur != NULL) {
        printf("%d -- ", cur->data);
        cur = cur->prev;
    }
    printf("HEAD]\n");
}

void clear_DList(DList* list) {
    Node* cur = list->head;
    while (cur != NULL) {
        Node* temp = cur;
        cur = cur->next;
        free(temp);
    }
    list->head = NULL;
    list->tail = NULL;
}